package com.huangmb.anymark.app.net;

import android.support.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.huangmb.androidlib.utils.Logger;
import com.huangmb.common.utils.IOUtils;
import com.huangmb.common.utils.StringUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

/**
 * @author hmb
 * @version 1.0
 * @since 2016/4/16 15:58
 */
public class HttpRequest implements Runnable {
    private static final String TAG = "HttpRequest";

    public static enum HttpType {
        GET, POST, PUT, DELET
    }

    private static final int TIMEOUT_MILLIS = 5000;

    private Connection.Method method = Connection.Method.GET;//http连接方式
    private String url;//链接，不带参数
    private Map<String, String> parameters;//参数

    private boolean hasCanceled = false;//是否该请求已被取消

    private HttpURLConnection httpURLConnection;//http连接对象

    private Callback callback;

    public HttpRequest() {

    }

    public HttpRequest(@NonNull String url, Callback callback) {
        this(url, Connection.Method.GET, null, callback);
    }

    public HttpRequest(@NonNull String url, Connection.Method method, Map<String, String> params, Callback callback) {
        this.url = url;
        this.parameters = params;
        this.method = method;
        this.callback = callback;
    }

    @Override
    public final void run() {
        try {
            Logger.d(TAG, "begin http request,url=" + url + ",method=" + method.toString());
            //使用Jsoup库访问网络
            Connection connect = Jsoup.connect(url)
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .timeout(TIMEOUT_MILLIS)
                    .ignoreContentType(true)
                    .method(method);

            if (parameters != null) {
                Iterator<Map.Entry<String, String>> iterator = parameters.entrySet().iterator();
                while (iterator.hasNext()){
                    Map.Entry<String, String> entry = iterator.next();
                    if(entry.getKey() == null || entry.getValue() == null){
                        iterator.remove();
                    }
                }

                connect.data(parameters);
            }
            //得到服务器返回的数据
            String content = connect.execute().body();
            Logger.d(TAG, content);
            if (!hasCanceled && callback != null) {
                //通知回调返回结果
                callback.onHttpResponse(content);
            }
        } catch (Exception e) {
            Logger.d(TAG, "error", e);

            if (!hasCanceled && callback != null) {
                callback.onNetworkError("网络连接异常");
            }
        } finally {
            RequestManager.getInstance().removeTask(this);//任务执行完成，从执行队列中移除，并进行下一个任务
        }

    }

    private String buildParams(List<RequestParameter> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        boolean isFirst = true;
        for (final RequestParameter param : list) {
            if (!isFirst) {
                sb.append("&");
            }
            sb.append(URLEncoder.encode(param.getKey()));
            sb.append("=");
            sb.append(URLEncoder.encode(param.getValue()));
            isFirst = false;
        }
        return sb.toString().trim();
    }

    private HttpURLConnection buildHttpConnection(String url, String param, HttpType method) {
        try {
            if (HttpType.GET == method && !StringUtils.isBlank(param)) {
                url += "?" + param;
            }
            URL u = new URL(url);
            HttpURLConnection httpURLConnection = (HttpURLConnection) u.openConnection();
            httpURLConnection.setConnectTimeout(TIMEOUT_MILLIS);
            httpURLConnection.setRequestProperty("Content-Type", "x-www-form-urlencoded");
            //httpURLConnection.setRequestProperty("Accept-Charset", "UTF-8");
            httpURLConnection.setRequestMethod(method.toString());
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setChunkedStreamingMode(0);
            //httpURLConnection.connect();
            if (param != null && HttpType.GET != method) {//不为get方式时的参数写入输出流中

                OutputStream stream = httpURLConnection.getOutputStream();
                stream.write(param.getBytes("UTF-8"));
                stream.flush();
                stream.close();
            }
            Logger.d(TAG, "b");
            return httpURLConnection;
        } catch (Exception e) {
            Logger.d(TAG, "buildHttpConnection error", e);
            return null;
        }
    }

    private String getContent(InputStream inputStream) {
        StringBuilder builder = new StringBuilder("");

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            String line;
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
        } catch (Exception e) {
            Logger.d(TAG, "read http response content error", e);
        } finally {
            IOUtils.close(inputStream);
        }
        return builder.toString();
    }


    public synchronized void cancel() {
        if (hasCanceled) {
            return;
        }
        hasCanceled = true;
        if (httpURLConnection != null) {
            try {
                httpURLConnection.disconnect();
            } catch (Exception e) {
                //
            }
            httpURLConnection = null;
        }
    }

    public Connection.Method getMethod() {
        return method;
    }

    public void setMethod(Connection.Method method) {
        this.method = method;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Map<String, String> getParameters() {
        return parameters;
    }

    public void setParameters(Map<String, String> parameters) {
        this.parameters = parameters;
    }

    public void addParameter(String key, String val) {
        if (parameters == null) {
            parameters = new HashMap<>();
        }
        parameters.put(key, val);
    }

    public interface Callback {
        void onNetworkError(String msg);

        void onHttpResponse(String content);
    }
}
